mTLS + カスタムドメインなAPI GatewayをSAMでデプロイしてみた
いわさです。
以前、SAMテンプレートとOpenAPIで最小限のAPI Gatewayをデプロイしました。
本日は、このテンプレートを流用して、カスタムドメインとmTLS(Mutual TLS)を使うようにカスタマイズしてみます。
カスタムドメインとmTLSの手動設定は以下の記事を参考に
上記記事が最高です。
API Gatewayでは本機能でクライアント認証を行うことが出来ます。
そもそもカスタムドメインを使いたかったのもありますが、mTLSを使う上でカスタムドメインの利用が前提条件にもなっています。
SAMテンプレート
今回は、手動でクライアント証明書を事前に発行しておき、Route53パブリックホストゾーンを作成済みな環境を想定しています。
テンプレートをつかって、mTLSとカスタムドメインが構成されたAPI Gatewayと、パブリック証明書用のACMをデプロイします。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: --- Parameters: ApiName: Description: API Gateway Name Type: String HostedZoneId: Description: Hosted Zone Id Type: String CustomDomainName: Description: Custom Domain Name Type: String TrustStoreS3Uri: Description: TrustStore S3 URI Type: String Default: s3://xxx/xxx.pem Resources: Api: Type: AWS::Serverless::Api Properties: Name: !Ref ApiName EndpointConfiguration: REGIONAL OpenApiVersion: 3.0.1 StageName: iwasa-stage DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: ./openapi.json Domain: DomainName: !Ref CustomDomainName CertificateArn: !Ref Certificate EndpointConfiguration: REGIONAL MutualTlsAuthentication: TruststoreUri: !Ref TrustStoreS3Uri Route53: DistributionDomainName: !Ref CustomDomainName HostedZoneId: !Ref HostedZoneId SecurityPolicy: TLS_1_2 Certificate: Type: AWS::CertificateManager::Certificate Properties: DomainName: !Ref CustomDomainName DomainValidationOptions: - DomainName: !Ref CustomDomainName HostedZoneId: !Ref HostedZoneId ValidationMethod: DNS
ポイントとして、mTLSを使う場合はTLSバージョンは1.2のみサポートされているのでSecurityPolicy
で明示する必要があります。
また、今回はパブリックドメインを使うのでOwnershipVerificationCertificateArn
の指定は不要です。
参考記事に記載があるように、MutualTlsAuthentication
でバージョンも指定することが推奨されていますが、ここでも割愛しています。
OpenAPIドキュメントはAWSのIPアドレスチェック用のエンドポイントをバックエンドに指しており、CodeBuildフェーズでsam package
しています。
詳細は前回の記事をご確認ください。
{ "openapi" : "3.0.1", "paths" : { "/" : { "get" : { "responses" : { "200" : { "description" : "200 response", "content" : { "application/json" : { "schema" : { "$ref" : "#/components/schemas/Empty" } } } } }, "x-amazon-apigateway-integration" : { "type" : "http_proxy", "httpMethod" : "GET", "uri" : "http://checkip.amazonaws.com", "responses" : { "default" : { "statusCode" : "200" } }, "passthroughBehavior" : "when_no_match" } } } }, "components" : { "schemas" : { "Empty" : { "title" : "Empty Schema", "type" : "object" } } } }
リソース構成と接続の確認
デプロイは前回の記事のCodePipelineにまかせていますのでそちらをご確認ください。
ここではデプロイ後にまず接続を試してみます。
$ curl https://apihoge.tak1wa.com curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to apihoge.tak1wa.com:443 $ curl --key my_client.key --cert my_client.pem https://apihoge.tak1wa.com 203.0.113.1
クライアント証明書を使ってアクセスしたときだけアクセス出来ていますね。
次に、リソース構成も見てみましょう。
mTLSがONになっており、カスタムドメインが設定されています。
さいごに
お気づきかもしれませんが、デフォルトエンドポイントが有効になっていますね。
この状態だと、クライアント証明書なしでデフォルトエンドポイント経由でアクセスすることが出来てしまいます。
$ curl https://4pqf8o4iqj.execute-api.ap-northeast-1.amazonaws.com/iwasa-stage 203.0.113.1
デフォルトエンドポイント周りはSAMやCloudFormationの場合は有効化/無効化に少し癖があることがわかったので別途検証記事を紹介したいと思います。